/*
 * Agent Client
 *
 * Created by Xiaowen.Zhu
 */

#pragma once

#include "cybertron/DefinesCore.hpp"
#include "cybertron/network/SocketTcpClient.hpp"

CYBERTRON_BEGIN

    enum AGENT_CLIENT_STATE {
        AGENT_CLIENT_STATE_CONNECTING,
        AGENT_CLIENT_STATE_CONNECTED,
        AGENT_CLIENT_STATE_DISCONNECTED,
    };

    class AgentClient {
    public:
        AgentClient(const std::string &srvAddr = "127.0.0.1", int srvPort = 5001);

        ~AgentClient();

        bool sendMessage(const Message &msg);
        bool sendMessage(std::uint16_t msgId,
            const google::protobuf::MessageLite& protobufMsg);

        void setHandlerDisconnected(std::function<void()> funcOnDisconnected);

        void setHandlerConnected(std::function<void()> funcOnConnected);

        void setHandlerMessage(std::function<void(const Message &)> funcOnMessage);

        void onTimer();

    protected:

    private:
        void perform();

        void onDisconnected();

        void onConnected();

        void onMessage(const Message &msg);

        std::shared_ptr<SocketTcpClient> mpClient;
        AGENT_CLIENT_STATE mState;
        std::function<void()> mFuncOnDisconnected;
        std::function<void()> mFuncOnConnected;
        std::function<void(const Message &)> mFuncOnMessage;

        std::recursive_mutex mLock;  //this lock is used to protected multiple thread accessing the mpClient handle
        //in the same time which may be set to nullptr when re-connecting

        std::string mServerAddr;
        int mServerPort;
    };


CYBERTRON_END